Move the relocate.setupRelocation code into XendDomain, removing the mutual
authoremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Wed, 30 Nov 2005 19:26:32 +0000 (19:26 +0000)
committeremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Wed, 30 Nov 2005 19:26:32 +0000 (19:26 +0000)
dependency between those two classes.

Split the XendDomain constructor into two pieces so that XendDomainInfo can
call XendDomain.instance even during the initial startup of XendDomain.

These two together mean that there is no need for the horrendous hack using
XendRoot.get_component to pass the singleton instance of XendDomain around.
Both XendRoot.get_component and XendRoot.add_component can go.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/XendRoot.py
tools/python/xen/xend/server/relocate.py

index 4e76acfdbebb8474de5ae8ae681150050de8e755..650a500e8ffb883b4b40317dcf4e5920e54f3610 100644 (file)
@@ -24,6 +24,7 @@
 
 import logging
 import os
+import socket
 import sys
 import threading
 
@@ -35,7 +36,6 @@ from xen.xend import XendRoot
 from xen.xend import XendCheckpoint
 from xen.xend.XendError import XendError
 from xen.xend.XendLogging import log
-from xen.xend.server import relocate
 from xen.xend.xenstore.xswatch import xswatch
 
 
@@ -54,15 +54,16 @@ class XendDomain:
     ## public:
     
     def __init__(self):
-        # Hack alert. Python does not support mutual imports, but XendDomainInfo
-        # needs access to the XendDomain instance to look up domains. Attempting
-        # to import XendDomain from XendDomainInfo causes unbounded recursion.
-        # So we stuff the XendDomain instance (self) into xroot's components.
-        xroot.add_component("xen.xend.XendDomain", self)
-
         self.domains = {}
         self.domains_lock = threading.RLock()
 
+
+    # This must be called only the once, by instance() below.  It is separate
+    # from the constructor because XendDomainInfo calls back into this class
+    # in order to check the uniqueness of domain names.  This means that
+    # instance() must be able to return a valid instance of this class even
+    # during this initialisation.
+    def init(self):
         self.domains_lock.acquire()
         try:
             self._add_domain(
@@ -389,10 +390,15 @@ class XendDomain:
         dominfo = self.domain_lookup(domid)
 
         port = xroot.get_xend_relocation_port()
-        sock = relocate.setupRelocation(dst, port)
+        try:
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            sock.connect((dst, port))
+        except socket.error, err:
+            raise XendError("can't connect: %s" % err[1])
 
+        sock.send("receive\n")
         XendCheckpoint.save(sock.fileno(), dominfo, live)
-        
+
 
     def domain_save(self, domid, dst):
         """Start saving a domain to file.
@@ -527,4 +533,5 @@ def instance():
         inst
     except:
         inst = XendDomain()
+        inst.init()
     return inst
index bbc7287f8206a2f55c8f68d0f40a2d90d42957ec..8f01f0aef050d3dedf6cc372634a83482c41eff1 100644 (file)
@@ -33,14 +33,14 @@ import xen.lowlevel.xc
 from xen.util import asserts
 from xen.util.blkif import blkdev_uname_to_file
 
-from xen.xend import image
-from xen.xend import sxp
-from xen.xend import XendRoot
+import image
+import sxp
+import uuid
+import XendDomain
+import XendRoot
+
 from xen.xend.XendBootloader import bootloader
 from xen.xend.XendError import XendError, VmError
-from xen.xend.XendRoot import get_component
-
-import uuid
 
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
@@ -338,9 +338,8 @@ def parseConfig(config):
 
 
 def domain_by_name(name):
-    # See comment in XendDomain constructor.
-    xd = get_component('xen.xend.XendDomain')
-    return xd.domain_lookup_by_name_nr(name)
+    return XendDomain.instance().domain_lookup_by_name_nr(name)
+
 
 def shutdown_reason(code):
     """Get a shutdown reason from a code.
@@ -1343,8 +1342,7 @@ class XendDomainInfo:
 
             new_dom = None
             try:
-                xd = get_component('xen.xend.XendDomain')
-                new_dom = xd.domain_create(config)
+                new_dom = XendDomain.instance().domain_create(config)
                 new_dom.unpause()
                 new_dom.removeVm(RESTART_IN_PROGRESS)
             except:
index 29398df90170ceb529e11605ebc16976eec18882..d94f63a58d0beceeafbbd124c799462961848075 100644 (file)
@@ -93,24 +93,6 @@ class XendRoot:
         self.configure()
 
 
-    def add_component(self, name, val):
-        """Add a xend component.
-
-        @param name: component name
-        @param val:  component object
-        """
-        self.components[name] = val
-
-    def get_component(self, name):
-        """Get a xend component from its name.
-        This is used as a work-round for problems caused by mutually
-        recursive imports.
-
-        @param name: component name
-        @return: component object (or None)
-        """
-        return self.components.get(name)
-
     def _logError(self, fmt, *args):
         """Logging function to log to stderr. We use this for XendRoot log
         messages because they may be logged before the logger has been
@@ -277,21 +259,3 @@ def instance():
     except:
         inst = XendRoot()
     return inst
-
-def add_component(name, val):
-    """Register a component with XendRoot.
-    This is used to work-round import cycles.
-
-    @param name: component name
-    @param val:  component value (often a module)
-    """
-    return instance().add_component(name, val)
-
-def get_component(name):
-    """Get a component.
-    This is used to work-round import cycles.
-
-    @param name: component name
-    @return component or None
-    """
-    return instance().get_component(name)
index f7cda14ec9fd8164627add3672e904b9cd9c564f..c179eaf6f76fa6c5fbdfa317d16205850d8d83ae 100644 (file)
@@ -23,16 +23,12 @@ import StringIO
 from xen.web import protocol, tcp, unix
 
 from xen.xend import sxp
-from xen.xend.XendError import XendError
+from xen.xend import XendDomain
 from xen.xend import XendRoot
+from xen.xend.XendError import XendError
 from xen.xend.XendLogging import log
 
 
-xroot = XendRoot.instance()
-
-
-DEBUG = 0
-
 class RelocationProtocol(protocol.Protocol):
     """Asynchronous handler for a connected relocation socket.
     """
@@ -111,8 +107,8 @@ class RelocationProtocol(protocol.Protocol):
         if self.transport:
             self.send_reply(["ready", name])
             self.transport.sock.setblocking(1)
-            xd = xroot.get_component("xen.xend.XendDomain")
-            xd.domain_restore_fd(self.transport.sock.fileno())
+            XendDomain.instance().domain_restore_fd(
+                self.transport.sock.fileno())
             self.transport.sock.setblocking(0)
         else:
             log.error(name + ": no transport")
@@ -120,6 +116,7 @@ class RelocationProtocol(protocol.Protocol):
 
 
 def listenRelocation():
+    xroot = XendRoot.instance()
     if xroot.get_xend_unix_server():
         path = '/var/lib/xend/relocation-socket'
         unix.listenUNIX(path, RelocationProtocol)
@@ -128,15 +125,3 @@ def listenRelocation():
         interface = xroot.get_xend_relocation_address()
         l = tcp.listenTCP(port, RelocationProtocol, interface=interface)
         l.setCloExec()
-
-def setupRelocation(dst, port):
-    try:
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        sock.connect((dst, port))
-    except socket.error, err:
-        raise XendError("can't connect: %s" % err[1])
-
-    sock.send("receive\n")
-    print sock.recv(80)
-
-    return sock